local-serverless-stack 0.5.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +105 -17
- package/bin/cli.js +68 -5
- package/dist/server/engine/backends/localstack-backend.d.ts +25 -0
- package/dist/server/engine/backends/localstack-backend.d.ts.map +1 -0
- package/dist/server/engine/backends/localstack-backend.js +199 -0
- package/dist/server/engine/backends/localstack-backend.js.map +1 -0
- package/dist/server/engine/backends/self-backend.d.ts +32 -0
- package/dist/server/engine/backends/self-backend.d.ts.map +1 -0
- package/dist/server/engine/backends/self-backend.js +205 -0
- package/dist/server/engine/backends/self-backend.js.map +1 -0
- package/dist/server/engine/bus.d.ts +10 -0
- package/dist/server/engine/bus.d.ts.map +1 -0
- package/dist/server/engine/bus.js +24 -0
- package/dist/server/engine/bus.js.map +1 -0
- package/dist/server/engine/dispatch/dispatcher.d.ts +46 -0
- package/dist/server/engine/dispatch/dispatcher.d.ts.map +1 -0
- package/dist/server/engine/dispatch/dispatcher.js +312 -0
- package/dist/server/engine/dispatch/dispatcher.js.map +1 -0
- package/dist/server/engine/dispatch/scheduler.d.ts +47 -0
- package/dist/server/engine/dispatch/scheduler.d.ts.map +1 -0
- package/dist/server/engine/dispatch/scheduler.js +328 -0
- package/dist/server/engine/dispatch/scheduler.js.map +1 -0
- package/dist/server/engine/dispatch/sqs-poller.d.ts +25 -0
- package/dist/server/engine/dispatch/sqs-poller.d.ts.map +1 -0
- package/dist/server/engine/dispatch/sqs-poller.js +242 -0
- package/dist/server/engine/dispatch/sqs-poller.js.map +1 -0
- package/dist/server/engine/dispatch/stream-tailer.d.ts +22 -0
- package/dist/server/engine/dispatch/stream-tailer.d.ts.map +1 -0
- package/dist/server/engine/dispatch/stream-tailer.js +205 -0
- package/dist/server/engine/dispatch/stream-tailer.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts +5 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.js +91 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts +24 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js +183 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts +29 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js +12 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts +13 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.js +244 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts +11 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.js +109 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts +23 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.js +541 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/index.d.ts +46 -0
- package/dist/server/engine/emulators/dynamodb/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/index.js +572 -0
- package/dist/server/engine/emulators/dynamodb/index.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/query.d.ts +12 -0
- package/dist/server/engine/emulators/dynamodb/query.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/query.js +237 -0
- package/dist/server/engine/emulators/dynamodb/query.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/schema.d.ts +58 -0
- package/dist/server/engine/emulators/dynamodb/schema.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/schema.js +284 -0
- package/dist/server/engine/emulators/dynamodb/schema.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/streams.d.ts +28 -0
- package/dist/server/engine/emulators/dynamodb/streams.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/streams.js +100 -0
- package/dist/server/engine/emulators/dynamodb/streams.js.map +1 -0
- package/dist/server/engine/emulators/events/index.d.ts +53 -0
- package/dist/server/engine/emulators/events/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/events/index.js +417 -0
- package/dist/server/engine/emulators/events/index.js.map +1 -0
- package/dist/server/engine/emulators/events/pattern.d.ts +3 -0
- package/dist/server/engine/emulators/events/pattern.d.ts.map +1 -0
- package/dist/server/engine/emulators/events/pattern.js +125 -0
- package/dist/server/engine/emulators/events/pattern.js.map +1 -0
- package/dist/server/engine/emulators/lambda-ctl/index.d.ts +55 -0
- package/dist/server/engine/emulators/lambda-ctl/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/lambda-ctl/index.js +461 -0
- package/dist/server/engine/emulators/lambda-ctl/index.js.map +1 -0
- package/dist/server/engine/emulators/s3/index.d.ts +45 -0
- package/dist/server/engine/emulators/s3/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/s3/index.js +591 -0
- package/dist/server/engine/emulators/s3/index.js.map +1 -0
- package/dist/server/engine/emulators/sns/index.d.ts +22 -0
- package/dist/server/engine/emulators/sns/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/sns/index.js +135 -0
- package/dist/server/engine/emulators/sns/index.js.map +1 -0
- package/dist/server/engine/emulators/sqs/index.d.ts +66 -0
- package/dist/server/engine/emulators/sqs/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/index.js +552 -0
- package/dist/server/engine/emulators/sqs/index.js.map +1 -0
- package/dist/server/engine/emulators/sqs/md5.d.ts +8 -0
- package/dist/server/engine/emulators/sqs/md5.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/md5.js +36 -0
- package/dist/server/engine/emulators/sqs/md5.js.map +1 -0
- package/dist/server/engine/emulators/sqs/queue.d.ts +105 -0
- package/dist/server/engine/emulators/sqs/queue.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/queue.js +371 -0
- package/dist/server/engine/emulators/sqs/queue.js.map +1 -0
- package/dist/server/engine/emulators/sts.d.ts +8 -0
- package/dist/server/engine/emulators/sts.d.ts.map +1 -0
- package/dist/server/engine/emulators/sts.js +23 -0
- package/dist/server/engine/emulators/sts.js.map +1 -0
- package/dist/server/engine/engine-backend.d.ts +17 -0
- package/dist/server/engine/engine-backend.d.ts.map +1 -0
- package/dist/server/engine/engine-backend.js +7 -0
- package/dist/server/engine/engine-backend.js.map +1 -0
- package/dist/server/engine/engine-manager.d.ts +22 -0
- package/dist/server/engine/engine-manager.d.ts.map +1 -0
- package/dist/server/engine/engine-manager.js +74 -0
- package/dist/server/engine/engine-manager.js.map +1 -0
- package/dist/server/engine/http/aws-chunked.d.ts +3 -0
- package/dist/server/engine/http/aws-chunked.d.ts.map +1 -0
- package/dist/server/engine/http/aws-chunked.js +50 -0
- package/dist/server/engine/http/aws-chunked.js.map +1 -0
- package/dist/server/engine/http/errors.d.ts +20 -0
- package/dist/server/engine/http/errors.d.ts.map +1 -0
- package/dist/server/engine/http/errors.js +43 -0
- package/dist/server/engine/http/errors.js.map +1 -0
- package/dist/server/engine/http/protocols/aws-json.d.ts +8 -0
- package/dist/server/engine/http/protocols/aws-json.d.ts.map +1 -0
- package/dist/server/engine/http/protocols/aws-json.js +42 -0
- package/dist/server/engine/http/protocols/aws-json.js.map +1 -0
- package/dist/server/engine/http/protocols/query-xml.d.ts +7 -0
- package/dist/server/engine/http/protocols/query-xml.d.ts.map +1 -0
- package/dist/server/engine/http/protocols/query-xml.js +35 -0
- package/dist/server/engine/http/protocols/query-xml.js.map +1 -0
- package/dist/server/engine/http/router.d.ts +8 -0
- package/dist/server/engine/http/router.d.ts.map +1 -0
- package/dist/server/engine/http/router.js +391 -0
- package/dist/server/engine/http/router.js.map +1 -0
- package/dist/server/engine/http/sigv4.d.ts +9 -0
- package/dist/server/engine/http/sigv4.d.ts.map +1 -0
- package/dist/server/engine/http/sigv4.js +33 -0
- package/dist/server/engine/http/sigv4.js.map +1 -0
- package/dist/server/engine/http/xml.d.ts +16 -0
- package/dist/server/engine/http/xml.d.ts.map +1 -0
- package/dist/server/engine/http/xml.js +92 -0
- package/dist/server/engine/http/xml.js.map +1 -0
- package/dist/server/engine/store/atomic.d.ts +4 -0
- package/dist/server/engine/store/atomic.d.ts.map +1 -0
- package/dist/server/engine/store/atomic.js +35 -0
- package/dist/server/engine/store/atomic.js.map +1 -0
- package/dist/server/engine/store/engine-store.d.ts +9 -0
- package/dist/server/engine/store/engine-store.d.ts.map +1 -0
- package/dist/server/engine/store/engine-store.js +218 -0
- package/dist/server/engine/store/engine-store.js.map +1 -0
- package/dist/server/engine/store/store-types.d.ts +37 -0
- package/dist/server/engine/store/store-types.d.ts.map +1 -0
- package/dist/server/engine/store/store-types.js +17 -0
- package/dist/server/engine/store/store-types.js.map +1 -0
- package/dist/server/engine/store/wal.d.ts +49 -0
- package/dist/server/engine/store/wal.d.ts.map +1 -0
- package/dist/server/engine/store/wal.js +328 -0
- package/dist/server/engine/store/wal.js.map +1 -0
- package/dist/server/engine/types.d.ts +137 -0
- package/dist/server/engine/types.d.ts.map +1 -0
- package/dist/server/engine/types.js +8 -0
- package/dist/server/engine/types.js.map +1 -0
- package/dist/server/index.js +12 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/services.d.ts.map +1 -1
- package/dist/server/routes/services.js +2 -0
- package/dist/server/routes/services.js.map +1 -1
- package/dist/server/runtime/runtime-worker.js +34 -11
- package/dist/server/runtime/runtime-worker.js.map +1 -1
- package/dist/server/services/artifact-resolver.d.ts +2 -0
- package/dist/server/services/artifact-resolver.d.ts.map +1 -0
- package/dist/server/services/artifact-resolver.js +38 -0
- package/dist/server/services/artifact-resolver.js.map +1 -0
- package/dist/server/services/cloudformation-parser.d.ts +41 -2
- package/dist/server/services/cloudformation-parser.d.ts.map +1 -1
- package/dist/server/services/cloudformation-parser.js +96 -6
- package/dist/server/services/cloudformation-parser.js.map +1 -1
- package/dist/server/services/config-manager.d.ts +29 -0
- package/dist/server/services/config-manager.d.ts.map +1 -1
- package/dist/server/services/config-manager.js +75 -6
- package/dist/server/services/config-manager.js.map +1 -1
- package/dist/server/services/lambda-runtime-manager.d.ts.map +1 -1
- package/dist/server/services/lambda-runtime-manager.js +2 -19
- package/dist/server/services/lambda-runtime-manager.js.map +1 -1
- package/dist/server/services/localstack-manager.d.ts +0 -7
- package/dist/server/services/localstack-manager.d.ts.map +1 -1
- package/dist/server/services/localstack-manager.js +11 -173
- package/dist/server/services/localstack-manager.js.map +1 -1
- package/dist/server/services/resource-provisioner.d.ts +7 -0
- package/dist/server/services/resource-provisioner.d.ts.map +1 -1
- package/dist/server/services/resource-provisioner.js +244 -18
- package/dist/server/services/resource-provisioner.js.map +1 -1
- package/dist/server/services/service-registrar.d.ts.map +1 -1
- package/dist/server/services/service-registrar.js +22 -4
- package/dist/server/services/service-registrar.js.map +1 -1
- package/dist/ui/assets/ApisPage-a9i2qD0Z.js +1 -0
- package/dist/ui/assets/BucketDetailPage-Cz27N0KV.js +1 -0
- package/dist/ui/assets/BucketsPage-CZ7wGmUN.js +1 -0
- package/dist/ui/assets/{DynamoPage-B1__Rjr2.js → DynamoPage-BZMs1iW8.js} +1 -1
- package/dist/ui/assets/DynamoTablePage-BQsGkhtO.js +3 -0
- package/dist/ui/assets/LambdaDetailPage-DJb7xqRB.js +4 -0
- package/dist/ui/assets/LambdasPage-Ctg1l-Lg.js +1 -0
- package/dist/ui/assets/OverviewPage-DiijblCA.js +1 -0
- package/dist/ui/assets/QueueDetailPage-DRpSqost.js +1 -0
- package/dist/ui/assets/QueuesPage-CY0bDGwV.js +1 -0
- package/dist/ui/assets/ServiceDetailPage-CYTEdtts.js +2 -0
- package/dist/ui/assets/ServicesPage-OlV_rr-q.js +2 -0
- package/dist/ui/assets/index-C1KdKPDS.css +1 -0
- package/dist/ui/assets/index-DA_C1HOg.js +36 -0
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/dist/ui/assets/ApisPage-DdgKjEdS.js +0 -1
- package/dist/ui/assets/BucketDetailPage-DZQGxm0y.js +0 -1
- package/dist/ui/assets/BucketsPage-xYXzxCvd.js +0 -1
- package/dist/ui/assets/DynamoTablePage-BCoxPdXW.js +0 -3
- package/dist/ui/assets/LambdaDetailPage-B85CA8tb.js +0 -4
- package/dist/ui/assets/LambdasPage-_TtxQMT_.js +0 -1
- package/dist/ui/assets/OverviewPage-CqTKTY64.js +0 -1
- package/dist/ui/assets/QueueDetailPage-BOr_sImA.js +0 -1
- package/dist/ui/assets/QueuesPage-DpByfcM5.js +0 -1
- package/dist/ui/assets/ServiceDetailPage-DsWgV-ad.js +0 -2
- package/dist/ui/assets/ServicesPage-CGlpsj98.js +0 -2
- package/dist/ui/assets/index-BWlB542w.js +0 -36
- package/dist/ui/assets/index-EYnsoJOq.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,82 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.0] - 2026-07-10
|
|
9
|
+
|
|
10
|
+
The self engine: an in-process AWS emulator that replaces LocalStack for the typical serverless dev loop — DynamoDB, SQS, S3, EventBridge, SNS (minimal), Lambda control plane and STS served by the orchestrator itself on one port. No Docker, no container, no auth token; boots in milliseconds; data persisted in local files. Opt-in (`engine: "self"` / `lss start --self-engine`) — LocalStack mode remains the default and fully supported. Design: `docs/PRD_SELF_ENGINE.md`; coverage matrix: `docs/SELF_ENGINE.md`.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Engine selection**: `engine: "localstack" | "self"` and a `selfEngine` config block (`port` default 14566 — deliberately outside the 4566–4599 range a real LocalStack intercepts on some hosts —, `dataDir`, `account`, `idleUnloadMs`, `memoryBudgetMb`, `fsync`, `fallbackEndpoint`); env overrides `LSS_ENGINE`/`LSS_ENGINE_PORT`; CLI `lss start --self-engine` (rejected when combined with the LocalStack-only `--external`/`--pro`/`--localstack-token`).
|
|
14
|
+
- **AWS wire front door** (`src/server/engine/http/`): one `node:http` listener routing by SigV4 credential scope → `X-Amz-Target` → path heuristics; per-protocol error serialization (JSON `__type`, Query XML, S3 XML with body-less HEAD errors, Lambda REST + `x-amzn-ErrorType`); the `x-amzn-query-error` SQS compat header; `aws-chunked` request decoding (SDK v3 streaming PutObject); `x-amzn-RequestId` on every response; `/_localstack/health` alias so existing readiness polls keep working; `selfEngine.fallbackEndpoint` reverse-proxies any unimplemented service/operation verbatim to a LocalStack during migration — unsupported calls otherwise fail loudly, never silently succeed.
|
|
15
|
+
- **File-backed store** (`src/server/engine/store/`): JSONL snapshot + append-only WAL per data table (torn-tail-safe replay, seq-based compaction), atomic JSON catalogs for metadata, content-addressed blob storage for S3 bodies (never held in the heap); registration writes metadata only — data hydrates on first touch (streamed line-by-line) and dehydrates after `idleUnloadMs` or under the `memoryBudgetMb` LRU budget; debounced flushes (20 ms / 256 KB) with opt-in fsync.
|
|
16
|
+
- **DynamoDB emulator** with a hand-rolled expression engine (KeyCondition/Condition/Filter/Update/Projection: comparators, `BETWEEN`/`IN`, boolean precedence, document paths, `SET`/`REMOVE`/`ADD`/`DELETE` with exact decimal-string `N` arithmetic), GSI/LSI queries with projection and sparse-index semantics, `Limit`-before-filter parity, `LastEvaluatedKey` paging (including index LEKs), lazy TTL (filtered at read, purged at compaction with Service-identity stream REMOVEs), stream records (`INSERT`/`MODIFY`/`REMOVE` per `StreamViewType`), batch ops, and the full `DescribeTable` introspection shape (`LatestStreamArn` present immediately).
|
|
17
|
+
- **SQS emulator**: FIFO (per-group ordering, 5-minute dedup window), event-driven long polling (parked promises — no polling loops), visibility-timeout redelivery, live `ApproximateNumberOfMessages*` counters (QueueInspector `await-idle`/metrics work unchanged), `MD5OfMessageBody`/`MD5OfMessageAttributes`, CreateQueue idempotent-success on identical attributes; messages are memory-only with a graceful-shutdown snapshot under `persistence`.
|
|
18
|
+
- **S3 emulator**: byte-exact object round trips, `Range` reads, `ListObjectsV2` (prefix/delimiter/CommonPrefixes/continuation/`encoding-type=url`), `DeleteObjects`, `CopyObject`, versioning flag, notification configuration (including the legacy `CloudFunctionConfiguration` XML names), quoted-MD5 ETags, `GetBucketLocation` us-east-1 quirk; multipart answers an explicit `NotImplemented` until the hardening phase.
|
|
19
|
+
- **EventBridge emulator**: buses, rules with validated patterns (exact, array-OR, `prefix`, `exists`, nested keys; unsupported operators rejected at `PutRule` with `InvalidEventPatternException`), targets, `PutEvents` with per-entry results, plus minimal **SNS** (topics + logged `Publish`) and **STS** (`GetCallerIdentity`).
|
|
20
|
+
- **Lambda control plane**: the provisioner's proxy functions are absorbed as metadata (zip discarded, `INVOKE_URL` kept — it doubles as the HTTP fallback for services still on serverless-offline), event source mappings with UUIDs persisted across restarts, `UpdateEventSourceMapping Enabled` = QueueInspector hold/release, `Invoke` honoring `X-Amz-Invocation-Type`.
|
|
21
|
+
- **In-process event dispatch** (`src/server/engine/dispatch/`): SQS delivery loops (batch size + `MaximumBatchingWindowInSeconds`, failure → visibility redelivery, capped backoff on runtime-unavailable), DynamoDB stream tailers (`TRIM_HORIZON`/`LATEST`, retry-then-advance with the `DDBStreamBatchInfo` OnFailure SQS envelope), S3 notification fan-out (event globs + prefix/suffix filters, `eventVersion 2.1` records), EventBridge target invocation (`Input`/`InputPath`) and **schedule triggering** (`rate()` + 6-field AWS cron, single timer wheel) — all delivered straight into the LSS Lambda runtime: no proxy Lambdas, no HTTP hop, no polling containers. Closes the long-standing scheduled-triggers TODO for self-engine mode.
|
|
22
|
+
- **Example `examples/self-engine-sample`**: three microservices (orders → billing → notifications) exercising DynamoDB + SQS (cross-service ESM by ARN) + S3 + EventBridge on the self engine, registered with `sls package` only. Measured: engine boot ~10 ms; the full pipeline across the three services completes in ~170 ms — no Docker.
|
|
23
|
+
- **Docs**: `docs/SELF_ENGINE.md` (coverage matrix, storage model, known divergences), `docs/PRD_SELF_ENGINE.md` (design), FEATURES.md §13, CONFIGURATION.md and README (self engine as the headline feature).
|
|
24
|
+
- **VS Code tasks** (`.vscode/tasks.json`, now versioned via a `.gitignore` exception): build/dev, unit/coverage/integration tests, lint, cross-project typecheck, a `validate: pre-prod` sequence (lint → typecheck → tests → build), and one-click flows for the self-engine and eventbridge examples (start/register/drive pipeline/stop).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **Dashboard component library updated**: `@treeui/vue` `^0.6.1` → `^0.10.0` (latest). No API changes required in the LSS components — `vue-tsc` and the Vite build pass unchanged.
|
|
28
|
+
- **Engine seam**: the LocalStack container lifecycle moved to `src/server/engine/backends/localstack-backend.ts`; `services/localstack-manager.ts` is now a thin facade over the new `EngineManager`, so the provisioner/explorers/seeds keep their imports and work against whichever engine is active (they always speak AWS SDK to `getConfig().endpoint`). Self-engine code is loaded via dynamic `import()` — LocalStack-mode memory footprint is unchanged.
|
|
29
|
+
- `lambdaRuntime.invokeHost` defaults to `127.0.0.1` in self-engine mode (nothing runs inside Docker); explicit config still wins.
|
|
30
|
+
- `GET /api/health` now includes an `engine: {kind, running, endpoint, ...}` block; the `localstack` boolean stays truthy when the active engine is healthy (client/UI compatibility).
|
|
31
|
+
- The root package version is now `0.8.0`. The `serverless-lss` plugin package was not changed.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **Branch-coverage gate restored to 100%**: closed the six uncovered branches left by the 0.7.0 EventBridge work (`cloudformation-parser.ts` — bus/rule with no `Properties`, rule with no `Targets`; `resource-provisioner.ts` — non-Error rejections in the event-rule pass and eventbus cleanup, `AddPermission` conflict/message-less fallbacks while wiring rule targets). `npm run test:coverage` passes again.
|
|
35
|
+
|
|
36
|
+
### Tests
|
|
37
|
+
- ~700 new unit tests (1802 total, up from 1100): wire router/SigV4/aws-chunked, store WAL/compaction/hydration/LRU-budget, DynamoDB expression engine (223 assertions) + emulator core, SQS/S3/EventBridge/SNS/STS/lambda-ctl emulators, dispatcher loops/stream tailers/scheduler, self-backend boot; engine selection covered in `config-manager` and `cli` suites. End-to-end smoke with real AWS SDK v3 clients against a booted engine (CRUD/Query/GSI, queue lifecycle, binary S3 round trip, per-entry PutEvents, ESM hold, restart persistence).
|
|
38
|
+
|
|
39
|
+
## [0.7.0] - 2026-07-10
|
|
40
|
+
|
|
41
|
+
EventBridge support: LSS can now provision the shared event bus and rule→Lambda triggers that previously required the last remaining `serverless deploy` (CloudFormation) step in local monorepo setups.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
- **`AWS::Events::EventBus` provisioning**: buses declared in the `resources:` section are created in LocalStack on registration (idempotent — re-registration tolerates an existing bus). `PutEvents` from handlers already worked via the SDK; the bus just had to exist.
|
|
45
|
+
- **`AWS::Events::Rule` triggers**: rules (event pattern or schedule, `ENABLED`/`DISABLED` state honored) are created on the declared bus and their Lambda targets wired through the same proxy model used by streams/SQS — EventBridge → proxy Lambda in LocalStack → LSS invoke API (130xx). Target `Input`/`InputPath` pass through; the bus is resolved from the template's logical ids, a literal name, or an ARN. Rules whose `EventBusName` can't be resolved from the template (e.g. `Fn::ImportValue`) are skipped with a warning instead of silently landing on the default bus.
|
|
46
|
+
- **Resources-only stacks**: a registered service that declares only `resources:` (no functions, no ports) provisions its resources without starting a runtime worker, gateway listeners or watcher — this already worked structurally since 0.5.0 gated those on declared functions/ports, and is now covered by tests for the EventBus-only infra-stack case.
|
|
47
|
+
- **Cleanup parity**: unregistering a service removes rule targets and rules first, then deletes its event buses.
|
|
48
|
+
- **Dashboard visibility**: EventBridge buses and rules show up in the service detail page (own sections) and as counters in the services list (`resourceBreakdown.buses`/`eventRules`), so a resources-only infra stack no longer renders as "N total" with an empty body.
|
|
49
|
+
- **Example `examples/eventbridge-sample`**: resources-only `events-stack` owning the shared bus (+ skipped Archive), a producer publishing `UserSignedUp` via `PutEvents`, and a consumer with an `events: eventBridge` trigger storing events in DynamoDB — registered with `sls package` only, no deploy. Its LocalStack runs on port `14566`, outside the standard 4566–4599 range, so a real LocalStack publishing that range (docker-compose defaults) can't intercept the example's `localhost` traffic on Docker Desktop/WSL2.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
- **EventBridge event shape through proxies**: the generated LocalStack proxy Lambda no longer wraps EventBridge events in a `Records` array — handlers receive `source`/`detail-type`/`detail` at the top level, exactly like on AWS. SQS/DynamoDB/SNS batches keep their `Records` shape. Proxies created by earlier versions keep the old code until recreated (only their `INVOKE_URL` is updated in place); delete the proxy function or reset LocalStack to pick up the fix.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
- `AWS::Events::Archive` resources are accepted and skipped with a registration warning: LocalStack mocks Archives (CloudFormation reports `CREATE_COMPLETE` but `ListArchives` stays empty), so provisioning one locally would only fake success.
|
|
56
|
+
- `CloudFormationParser.parse()` accepts an optional warnings sink; the registrar forwards template-level warnings (like skipped Archives) to the registering client alongside state-file warnings.
|
|
57
|
+
- New runtime dependency: `@aws-sdk/client-eventbridge`.
|
|
58
|
+
|
|
59
|
+
### Tests
|
|
60
|
+
- Parser coverage for `AWS::Events::EventBus`/`Rule`/`Archive` (bus name fallback, pattern/schedule/state, `Fn::ImportValue` flagging, literal-ARN targets, warning sink) and ResourceProvisioner coverage for bus creation, rule wiring (proxy reuse, permissions, default vs named vs literal bus), unresolvable-bus/unsupported-target skips, and cleanup ordering.
|
|
61
|
+
|
|
62
|
+
## [0.6.0] - 2026-07-09
|
|
63
|
+
|
|
64
|
+
Corrections from integrating LSS 0.5.0 in a real monorepo using osls 4, serverless-esbuild ESM artifacts, HTTP API v2 authorizers, DynamoDB Streams, and Docker-in-Docker devcontainers.
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
- **Configurable LocalStack proxy callback host**: `lambdaRuntime.invokeHost` and `LSS_INVOKE_HOST` now control the host used when generated LocalStack Lambda proxies call back into LSS's invoke listener. The default remains `host.docker.internal`; devcontainers/DinD can point it at the Docker network gateway (for example `172.19.0.1`).
|
|
68
|
+
- **Native TypeScript source loading when available**: in `source` mode, the runtime worker now tries Node's native TypeScript type stripping (`process.features.typescript`) before requiring `esbuild-register`, `tsx`, or `ts-node`.
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
- **Artifact resolution for osls/serverless package output**: `package.artifact` values such as `s7-identity.zip` are now resolved relative to `.serverless/` as well as the service root, and nonexistent declared candidates no longer suppress the `.serverless/*.zip` scan fallback.
|
|
72
|
+
- **Stale LocalStack proxy `INVOKE_URL`**: re-registering a service now updates an existing proxy Lambda when the expected invoke URL changed (port renumbering or `invokeHost` changes).
|
|
73
|
+
- **Service identity collisions**: service registration now uses the `service:` name from `serverless-state.json` instead of the directory basename, with migration for same-root legacy cache entries.
|
|
74
|
+
- **Event source mapping fidelity**: CloudFormation `StartingPosition`, `MaximumRetryAttempts`, `FunctionResponseTypes`, `MaximumBatchingWindowInSeconds`, `FilterCriteria`, and `DestinationConfig.OnFailure` are parsed/applied where supported; duplicate checks compare the resolved live ARN instead of unresolved CFN refs.
|
|
75
|
+
- **DynamoDB table fidelity**: `StreamViewType` is preserved and `TimeToLiveSpecification` is applied after table creation or on re-registration, including disabled TTL declarations.
|
|
76
|
+
- **CLI stop/start race**: `lss stop` now waits for the orchestrator process to exit (with timeout) before returning, reducing immediate `lss start` failures from a still-bound port.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
- The root package version is now `0.6.0`. The `serverless-lss` plugin package was not changed.
|
|
80
|
+
|
|
81
|
+
### Tests
|
|
82
|
+
- Added/updated unit coverage for artifact resolution, Lambda runtime config env overrides, CloudFormation parsing, ResourceProvisioner proxy/TTL/event-source behavior, and the async CLI stop flow.
|
|
83
|
+
|
|
8
84
|
## [0.5.0] - 2026-07-08
|
|
9
85
|
|
|
10
86
|
API Gateway & Lambda runtime emulation: LSS now registers every function and HTTP route a service declares, executes the handlers itself in per-service workers, and answers on the service's own API (30xx) and Lambda-invoke (130xx) ports — making `serverless-offline` optional. Monorepo callers and the LocalStack event proxies keep their ports and contracts unchanged; only the process answering changes.
|
package/README.md
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/local-serverless-stack)
|
|
4
4
|
|
|
5
|
-
**Local control plane for serverless development with LocalStack orchestration**
|
|
5
|
+
**Local control plane for serverless development — with its own in-process AWS engine (no Docker) or LocalStack orchestration**
|
|
6
6
|
|
|
7
|
-
LSS provides a unified local development environment for serverless microservices, eliminating the need to run separate LocalStack instances
|
|
7
|
+
LSS provides a unified local development environment for serverless microservices: one orchestrator provisions and serves every AWS resource your services declare, eliminating the need to run separate LocalStack instances (or, with the **self engine**, any LocalStack at all).
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
- **
|
|
13
|
-
- **Event source mappings**: Automatically connects SQS queues to Lambda handlers
|
|
14
|
-
- **Lambda
|
|
11
|
+
- **⚡ Self engine (the LSS differentiator)**: DynamoDB, SQS, S3, EventBridge, SNS and the Lambda control plane emulated **in-process** by the orchestrator — no Docker, no LocalStack, no auth token. Boots in milliseconds, stores data in local files, delivers events straight into your handlers. See [Self engine](#self-engine--no-docker-no-localstack-no-auth-token) below.
|
|
12
|
+
- **Centralized provisioning**: Parses CloudFormation templates from `sls package` and provisions resources automatically — into the self engine or a single shared LocalStack, your choice per instance
|
|
13
|
+
- **Event source mappings**: Automatically connects SQS queues, streams, S3 notifications and EventBridge rules to Lambda handlers
|
|
14
|
+
- **Lambda runtime & API emulation**: LSS answers on the same API (30xx) and Lambda invoke (130xx) ports that serverless-offline used
|
|
15
15
|
- **Web UI**: Vue 3 dashboard to monitor services, resources, and event mappings
|
|
16
16
|
- **Hot reload**: Watch for code changes and auto-rebuild/reprovision
|
|
17
17
|
- **Process management**: Start/stop microservices from the orchestrator
|
|
@@ -19,6 +19,57 @@ LSS provides a unified local development environment for serverless microservice
|
|
|
19
19
|
|
|
20
20
|
See [docs/FEATURES.md](docs/FEATURES.md) for the complete feature inventory and how each capability is tested.
|
|
21
21
|
|
|
22
|
+
## Self engine — no Docker, no LocalStack, no auth token
|
|
23
|
+
|
|
24
|
+
LocalStack got heavy (a container eating 1 GB+ of RAM) and stopped being free by default
|
|
25
|
+
(community images `>= 2026.5` require an auth token). The **self engine** replaces it for
|
|
26
|
+
the typical serverless dev loop: the orchestrator itself serves the real AWS wire
|
|
27
|
+
protocols on one port, so your application code, the AWS SDK, the dashboard and `lss seed`
|
|
28
|
+
all work unchanged — there is simply no container underneath.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx lss start --self-engine # or "engine": "self" in lss.config.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
AWS_ENDPOINT=http://localhost:14566 # point your services here, done
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
What you get:
|
|
39
|
+
|
|
40
|
+
- **DynamoDB** with the full expression language (KeyCondition/Filter/Update/Projection,
|
|
41
|
+
exact decimal arithmetic), GSIs/LSIs, TTL and streams — items persisted in local
|
|
42
|
+
JSONL files under `~/.lss/engine/`, hydrated lazily and unloaded when idle.
|
|
43
|
+
- **SQS** with FIFO, visibility redelivery and live counters; **S3** with byte-exact
|
|
44
|
+
object round trips and notifications; **EventBridge** with buses, pattern-filtered
|
|
45
|
+
rules and `rate()`/cron schedules; minimal **SNS** and **STS**.
|
|
46
|
+
- **Events delivered in-process**: SQS batches, DynamoDB streams, S3 notifications and
|
|
47
|
+
EventBridge targets go straight from the engine to the LSS Lambda runtime — no proxy
|
|
48
|
+
Lambdas, no polling containers.
|
|
49
|
+
|
|
50
|
+
```mermaid
|
|
51
|
+
flowchart LR
|
|
52
|
+
APP[Your services<br/>AWS SDK → :14566] --> ENG
|
|
53
|
+
subgraph ORCH["One orchestrator process — no Docker"]
|
|
54
|
+
ENG[Self engine<br/>DynamoDB · SQS · S3<br/>EventBridge · SNS · STS]
|
|
55
|
+
ENG -->|in-process events| RT[LSS Lambda runtime<br/>your handlers, ports 30xx/130xx]
|
|
56
|
+
ENG --- FS[(local files<br/>~/.lss/engine)]
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Measured on [examples/self-engine-sample](examples/self-engine-sample/) (3 microservices:
|
|
61
|
+
orders → billing → notifications): engine boot **~10 ms**; a full pipeline crossing
|
|
62
|
+
DynamoDB + SQS + S3 + EventBridge across the three services completes in **~170 ms** —
|
|
63
|
+
with the whole stack being the orchestrator process plus one small worker per service.
|
|
64
|
+
|
|
65
|
+
Migration is gradual: LocalStack mode remains the default and fully supported; a running
|
|
66
|
+
instance picks one engine. Anything the self engine doesn't implement yet answers with an
|
|
67
|
+
explicit error naming the operation — or is forwarded verbatim to a LocalStack via
|
|
68
|
+
`selfEngine.fallbackEndpoint`. Coverage matrix and storage model:
|
|
69
|
+
[docs/SELF_ENGINE.md](docs/SELF_ENGINE.md) · design/PRD:
|
|
70
|
+
[docs/PRD_SELF_ENGINE.md](docs/PRD_SELF_ENGINE.md) · runnable demo:
|
|
71
|
+
[examples/self-engine-sample](examples/self-engine-sample/).
|
|
72
|
+
|
|
22
73
|
## Architecture
|
|
23
74
|
|
|
24
75
|
```
|
|
@@ -41,18 +92,18 @@ local-serverless-stack/
|
|
|
41
92
|
|
|
42
93
|
**Components**:
|
|
43
94
|
- **CLI** (`bin/cli.js`): Background process management (start/stop/status/logs)
|
|
44
|
-
- **Server** (`src/server/`): Express API +
|
|
95
|
+
- **Server** (`src/server/`): Express API + engine orchestration
|
|
96
|
+
- **Engine** (`src/server/engine/`): the AWS provider behind everything — either the in-process **self engine** (port 14566, no Docker) or a managed/external **LocalStack** container (port 4566)
|
|
45
97
|
- **UI** (`src/ui/`): Vue 3 dashboard for monitoring
|
|
46
98
|
- **Plugin** (`packages/serverless-plugin/`): Auto-registration for Serverless Framework
|
|
47
|
-
- **LocalStack**: Docker container (port 4566) with AWS services
|
|
48
99
|
|
|
49
100
|
## Quick Start
|
|
50
101
|
|
|
51
102
|
### Prerequisites
|
|
52
103
|
|
|
53
|
-
- Node.js >=
|
|
54
|
-
- Docker (for LocalStack)
|
|
104
|
+
- Node.js >= 20
|
|
55
105
|
- Serverless Framework 3.40.0
|
|
106
|
+
- Docker — **only for the LocalStack engine**; the self engine (`--self-engine`) needs none
|
|
56
107
|
|
|
57
108
|
### Installation
|
|
58
109
|
|
|
@@ -86,9 +137,12 @@ See the [plugin documentation](packages/serverless-plugin/README.md) for configu
|
|
|
86
137
|
LSS provides a simple CLI to manage the orchestrator in background mode:
|
|
87
138
|
|
|
88
139
|
```bash
|
|
89
|
-
# Start the orchestrator in background
|
|
140
|
+
# Start the orchestrator in background (managed LocalStack)
|
|
90
141
|
npx lss start
|
|
91
142
|
|
|
143
|
+
# Start with the in-process self engine instead — no Docker
|
|
144
|
+
npx lss start --self-engine
|
|
145
|
+
|
|
92
146
|
# Check if orchestrator is running
|
|
93
147
|
npx lss status
|
|
94
148
|
|
|
@@ -105,6 +159,12 @@ npx lss help
|
|
|
105
159
|
### CLI Output
|
|
106
160
|
|
|
107
161
|
```bash
|
|
162
|
+
$ npx lss start --self-engine
|
|
163
|
+
🚀 LSS Orchestrator started (PID: 12345)
|
|
164
|
+
📊 Server: http://localhost:3100
|
|
165
|
+
🔧 Self Engine: http://localhost:14566 (no Docker)
|
|
166
|
+
✅ Service is running
|
|
167
|
+
|
|
108
168
|
$ npx lss start
|
|
109
169
|
🚀 LSS Orchestrator started (PID: 12345)
|
|
110
170
|
📊 Dashboard: http://localhost:3100
|
|
@@ -178,19 +238,19 @@ npx lss start
|
|
|
178
238
|
cd your-microservice
|
|
179
239
|
npx sls package
|
|
180
240
|
|
|
181
|
-
# 3.
|
|
182
|
-
npx serverless offline start --host 0.0.0.0 --httpPort 3020 --lambdaPort 13020
|
|
183
|
-
|
|
184
|
-
# 4. Monitor in the dashboard
|
|
241
|
+
# 3. Monitor in the dashboard
|
|
185
242
|
open http://localhost:3100
|
|
186
243
|
```
|
|
187
244
|
|
|
188
245
|
Now when you send a message to an SQS queue in LocalStack, the orchestrator will:
|
|
189
246
|
1. Detect the event via event source mapping
|
|
190
247
|
2. Invoke the Lambda proxy in LocalStack
|
|
191
|
-
3. Proxy
|
|
248
|
+
3. Proxy calls LSS's Lambda invoke listener on the service invoke port
|
|
192
249
|
4. Your handler executes
|
|
193
250
|
|
|
251
|
+
If you still want serverless-offline to own the ports for a service, disable the
|
|
252
|
+
LSS runtime globally or per service with `lambdaRuntime.enabled`/`serviceRuntime`.
|
|
253
|
+
|
|
194
254
|
## Project Structure
|
|
195
255
|
|
|
196
256
|
```
|
|
@@ -214,13 +274,30 @@ local-serverless-stack/
|
|
|
214
274
|
### Environment Variables
|
|
215
275
|
|
|
216
276
|
- `PORT`: Orchestrator API port (default: 3100)
|
|
277
|
+
- `LSS_ENGINE`: AWS engine — `localstack` (default) or `self` (in-process, no Docker)
|
|
278
|
+
- `LSS_ENGINE_PORT`: Self engine port (default: 14566)
|
|
217
279
|
- `ENABLE_DYNAMO_PROXY`: Enable DynamoDB proxy on port 8000 (default: false)
|
|
218
280
|
- `DYNAMO_PROXY_PORT`: DynamoDB proxy port (default: 8000)
|
|
219
281
|
|
|
282
|
+
### Engine selection
|
|
283
|
+
|
|
284
|
+
```jsonc
|
|
285
|
+
// lss.config.json
|
|
286
|
+
{
|
|
287
|
+
"engine": "self", // "localstack" (default) | "self"
|
|
288
|
+
"selfEngine": { "port": 14566 } // full reference: docs/SELF_ENGINE.md
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The self engine's default port sits **outside 4566–4599** on purpose: a real LocalStack
|
|
293
|
+
install intercepts that whole range on some hosts (Docker Desktop/WSL2). `--self-engine`
|
|
294
|
+
cannot be combined with the LocalStack-only flags (`--external`, `--pro`,
|
|
295
|
+
`--localstack-token`).
|
|
296
|
+
|
|
220
297
|
### LocalStack Settings
|
|
221
298
|
|
|
222
299
|
LocalStack is configured with:
|
|
223
|
-
- Services: `dynamodb,sqs,sns,s3,lambda`
|
|
300
|
+
- Services: `dynamodb,sqs,sns,s3,lambda,events`
|
|
224
301
|
- Persistence: Enabled (volume: `lss-localstack-data`)
|
|
225
302
|
- Lambda executor: `local` (no Docker-in-Docker required)
|
|
226
303
|
- Docker socket: Mounted from host
|
|
@@ -479,6 +556,17 @@ sequenceDiagram
|
|
|
479
556
|
- Response returned through proxy chain
|
|
480
557
|
- Message deleted from queue on success, or sent to DLQ on failure
|
|
481
558
|
|
|
559
|
+
> **Self-engine mode collapses this whole chain**: the engine's event source mapping
|
|
560
|
+
> delivers the SQS batch **in-process** to the LSS Lambda runtime — no LocalStack
|
|
561
|
+
> polling, no proxy Lambda, no HTTP hop:
|
|
562
|
+
>
|
|
563
|
+
> ```
|
|
564
|
+
> LocalStack mode: SQS → LocalStack ESM → proxy Lambda (container) → HTTP → handler
|
|
565
|
+
> Self engine: SQS (engine) → dispatcher → handler
|
|
566
|
+
> ```
|
|
567
|
+
>
|
|
568
|
+
> The same applies to DynamoDB streams, S3 notifications and EventBridge targets.
|
|
569
|
+
|
|
482
570
|
## CLI Implementation Details
|
|
483
571
|
|
|
484
572
|
The `npx lss` CLI is implemented in `/bin/cli.js` and provides:
|
package/bin/cli.js
CHANGED
|
@@ -96,6 +96,8 @@ function getConfig(config) {
|
|
|
96
96
|
localstackImage: config.localstackImage,
|
|
97
97
|
localstackAuthToken: config.localstackAuthToken,
|
|
98
98
|
stateDir: config.stateDir,
|
|
99
|
+
engine: config.engine || 'localstack',
|
|
100
|
+
selfEnginePort: (config.selfEngine && config.selfEngine.port) || 14566,
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
|
|
@@ -150,7 +152,11 @@ function startOrchestrator() {
|
|
|
150
152
|
const cfg = getConfig(config);
|
|
151
153
|
console.log('✅ LSS Orchestrator already running (PID:', pid + ')');
|
|
152
154
|
console.log(`📊 Server: http://localhost:${cfg.serverPort}`);
|
|
153
|
-
|
|
155
|
+
if (cfg.engine === 'self') {
|
|
156
|
+
console.log(`🔧 Self Engine: http://localhost:${cfg.selfEnginePort}`);
|
|
157
|
+
} else {
|
|
158
|
+
console.log(`🔧 LocalStack: http://localhost:${cfg.localstackPort}`);
|
|
159
|
+
}
|
|
154
160
|
if (cfg.enableDynamoProxy) {
|
|
155
161
|
console.log(`🔄 DynamoDB Proxy: http://localhost:${cfg.dynamoProxyPort} (enabled)`);
|
|
156
162
|
}
|
|
@@ -183,6 +189,13 @@ function startOrchestrator() {
|
|
|
183
189
|
const useExternal = process.argv.includes('--external');
|
|
184
190
|
const usePro = process.argv.includes('--pro');
|
|
185
191
|
const cliToken = getArgValue('--localstack-token');
|
|
192
|
+
const useSelfEngine = process.argv.includes('--self-engine');
|
|
193
|
+
|
|
194
|
+
const engine = useSelfEngine ? 'self' : cfg.engine;
|
|
195
|
+
if (engine === 'self' && (useExternal || usePro || cliToken)) {
|
|
196
|
+
console.error('❌ --self-engine cannot be combined with --external, --pro or --localstack-token (those are LocalStack options).');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
186
199
|
|
|
187
200
|
const mode = useExternal ? 'external' : cfg.mode;
|
|
188
201
|
const edition = usePro ? 'pro' : cfg.localstackEdition;
|
|
@@ -223,6 +236,9 @@ function startOrchestrator() {
|
|
|
223
236
|
if (authToken) {
|
|
224
237
|
env.LOCALSTACK_AUTH_TOKEN = authToken;
|
|
225
238
|
}
|
|
239
|
+
if (engine === 'self') {
|
|
240
|
+
env.LSS_ENGINE = 'self';
|
|
241
|
+
}
|
|
226
242
|
// Hand the same config file to the server so its ConfigManager reads the
|
|
227
243
|
// identical serverPort/localstackPort/seedsDir/region/mode (not just the
|
|
228
244
|
// hand-translated subset above). Keeps the two config loaders in agreement.
|
|
@@ -243,7 +259,11 @@ function startOrchestrator() {
|
|
|
243
259
|
|
|
244
260
|
console.log('🚀 LSS Orchestrator started (PID:', child.pid + ')');
|
|
245
261
|
console.log(`📊 Server: http://localhost:${cfg.serverPort}`);
|
|
246
|
-
|
|
262
|
+
if (engine === 'self') {
|
|
263
|
+
console.log(`🔧 Self Engine: http://localhost:${cfg.selfEnginePort} (no Docker)`);
|
|
264
|
+
} else {
|
|
265
|
+
console.log(`🔧 LocalStack: http://localhost:${cfg.localstackPort} (mode: ${mode}, edition: ${edition})`);
|
|
266
|
+
}
|
|
247
267
|
if (enableDynamoProxy) {
|
|
248
268
|
console.log(`🔄 DynamoDB Proxy: http://localhost:${cfg.dynamoProxyPort} (enabled)`);
|
|
249
269
|
}
|
|
@@ -262,7 +282,40 @@ function startOrchestrator() {
|
|
|
262
282
|
}, 2000);
|
|
263
283
|
}
|
|
264
284
|
|
|
265
|
-
|
|
285
|
+
// Poll kill(pid, 0) until the process is gone. SIGTERM alone isn't enough to
|
|
286
|
+
// return from `stop`: an immediate `lss start` would race the dying orchestrator
|
|
287
|
+
// for the server port and crash with EADDRINUSE.
|
|
288
|
+
function waitForExit(pid, timeoutMs = 10000, intervalMs = 200) {
|
|
289
|
+
return new Promise(resolve => {
|
|
290
|
+
const deadline = Date.now() + timeoutMs;
|
|
291
|
+
let timer;
|
|
292
|
+
let done = false;
|
|
293
|
+
const finish = (value) => {
|
|
294
|
+
done = true;
|
|
295
|
+
if (timer) clearInterval(timer);
|
|
296
|
+
resolve(value);
|
|
297
|
+
};
|
|
298
|
+
const check = () => {
|
|
299
|
+
try {
|
|
300
|
+
process.kill(pid, 0);
|
|
301
|
+
} catch (e) {
|
|
302
|
+
finish(true);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (Date.now() >= deadline) {
|
|
306
|
+
finish(false);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
// Fast path: the process is often already gone — check synchronously so
|
|
310
|
+
// `stop` resolves without ever scheduling (and leaking) an interval.
|
|
311
|
+
check();
|
|
312
|
+
if (!done) {
|
|
313
|
+
timer = setInterval(check, intervalMs);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function stopOrchestrator() {
|
|
266
319
|
const { pidFile } = runtimePaths();
|
|
267
320
|
if (!fs.existsSync(pidFile)) {
|
|
268
321
|
console.log('⚠️ LSS Orchestrator is not running');
|
|
@@ -273,13 +326,20 @@ function stopOrchestrator() {
|
|
|
273
326
|
|
|
274
327
|
try {
|
|
275
328
|
process.kill(pid, 'SIGTERM');
|
|
276
|
-
fs.unlinkSync(pidFile);
|
|
277
|
-
console.log('🛑 LSS Orchestrator stopped (PID:', pid + ')');
|
|
278
329
|
} catch (e) {
|
|
279
330
|
console.error('❌ Failed to stop process:', e.message);
|
|
280
331
|
if (fs.existsSync(pidFile)) {
|
|
281
332
|
fs.unlinkSync(pidFile);
|
|
282
333
|
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const exited = await waitForExit(pid);
|
|
338
|
+
fs.unlinkSync(pidFile);
|
|
339
|
+
if (exited) {
|
|
340
|
+
console.log('🛑 LSS Orchestrator stopped (PID:', pid + ')');
|
|
341
|
+
} else {
|
|
342
|
+
console.warn(`⚠️ Process ${pid} did not exit within 10s of SIGTERM — the server port may still be busy. Check \`lss status\` before starting again.`);
|
|
283
343
|
}
|
|
284
344
|
}
|
|
285
345
|
|
|
@@ -598,6 +658,7 @@ Options:
|
|
|
598
658
|
Applies to start/stop/status/logs so an isolated instance
|
|
599
659
|
can be addressed without cd-ing into its folder.
|
|
600
660
|
--enable-dynamo-proxy Enable DynamoDB proxy on port 8000 (for start command)
|
|
661
|
+
--self-engine Use the in-process AWS engine instead of LocalStack (no Docker)
|
|
601
662
|
--external Connect to a LocalStack already running, do not spawn a container
|
|
602
663
|
--pro Use the LocalStack Pro image (requires LOCALSTACK_AUTH_TOKEN)
|
|
603
664
|
--localstack-token <token> Pass a LOCALSTACK_AUTH_TOKEN to the container
|
|
@@ -637,6 +698,7 @@ Configuration:
|
|
|
637
698
|
|
|
638
699
|
Examples:
|
|
639
700
|
npx lss start # Start the orchestrator (managed LocalStack)
|
|
701
|
+
npx lss start --self-engine # Use the in-process engine (no Docker, port 14566)
|
|
640
702
|
npx lss start --enable-dynamo-proxy # Start with DynamoDB proxy enabled
|
|
641
703
|
npx lss start --external # Connect to an external LocalStack
|
|
642
704
|
npx lss start --pro # Use LocalStack Pro (token required)
|
|
@@ -687,6 +749,7 @@ module.exports = {
|
|
|
687
749
|
getArgValue,
|
|
688
750
|
runtimePaths,
|
|
689
751
|
getOrchestratorPath,
|
|
752
|
+
waitForExit,
|
|
690
753
|
formatError,
|
|
691
754
|
buildHttpError,
|
|
692
755
|
firstPositional,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { EngineBackend } from '../engine-backend.js';
|
|
2
|
+
export declare class LocalStackBackend implements EngineBackend {
|
|
3
|
+
readonly kind: "localstack";
|
|
4
|
+
private process;
|
|
5
|
+
private _isRunning;
|
|
6
|
+
private endpoint;
|
|
7
|
+
private readonly containerName;
|
|
8
|
+
private readonly configManager;
|
|
9
|
+
constructor();
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
private waitForReady;
|
|
13
|
+
isRunning(): boolean;
|
|
14
|
+
getEndpoint(): string;
|
|
15
|
+
getConfig(): {
|
|
16
|
+
endpoint: string;
|
|
17
|
+
region: string;
|
|
18
|
+
credentials: {
|
|
19
|
+
accessKeyId: string;
|
|
20
|
+
secretAccessKey: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
healthDetail(): Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=localstack-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localstack-backend.d.ts","sourceRoot":"","sources":["../../../../src/server/engine/backends/localstack-backend.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IAKzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;;IASxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+HtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAwBb,YAAY;IAmB1B,SAAS,IAAI,OAAO;IAIpB,WAAW,IAAI,MAAM;IAIrB,SAAS;;;;;;;;IAWT,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQxC"}
|